/*
 * @Author: 0x9DEFA478
 * @Date: 2022-01-23 15:19:46
 * @LastEditTime: 2022-08-20 16:51:55
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#ifndef __H_NES_H_
#define __H_NES_H_
#include "./API/H_NES_Config.h"




#define vH_NES_StandardControllerStatus_1P_A                      0x0001U
#define vH_NES_StandardControllerStatus_1P_B                      0x0002U
#define vH_NES_StandardControllerStatus_1P_Select                 0x0004U
#define vH_NES_StandardControllerStatus_1P_Start                  0x0008U
#define vH_NES_StandardControllerStatus_1P_Up                     0x0010U
#define vH_NES_StandardControllerStatus_1P_Down                   0x0020U
#define vH_NES_StandardControllerStatus_1P_Left                   0x0040U
#define vH_NES_StandardControllerStatus_1P_Right                  0x0080U

#define vH_NES_StandardControllerStatus_2P_A                      0x0100U
#define vH_NES_StandardControllerStatus_2P_B                      0x0200U
#define vH_NES_StandardControllerStatus_2P_Select                 0x0400U
#define vH_NES_StandardControllerStatus_2P_Start                  0x0800U
#define vH_NES_StandardControllerStatus_2P_Up                     0x1000U
#define vH_NES_StandardControllerStatus_2P_Down                   0x2000U
#define vH_NES_StandardControllerStatus_2P_Left                   0x4000U
#define vH_NES_StandardControllerStatus_2P_Right                  0x8000U




#define vH_NES_TelevisionStandards_NTSC                           1
#define vH_NES_TelevisionStandards_PAL                            2
#define vH_NES_TelevisionStandards_Dendy                          3




#define vH_NES_Result_ROMNotLoad                                  4    //ROM未加载
#define vH_NES_Result_ROMLoaded                                   3    //ROM已经加载
#define vH_NES_Result_Running                                     2    //H_NES正在运行
#define vH_NES_Result_Stopped                                     1    //H_NES已经停止
#define vH_NES_Result_OK                                          0
#define vH_NES_Result_UnknowError                                 -1

#define vH_NES_Result_ROMError                                    -2   //不能识别的ROM
#define vH_NES_Result_MapperNoSupport                             -3   //不支持的Mapper
#define vH_NES_Result_PRG_RAM_AllocFail                           -4   //PRG_RAM分配失败
#define vH_NES_Result_CHR_RAM_AllocFail                           -5   //CHR_RAM分配失败

#define vH_NES_Result_FetchInstructionFail                        -6   //意外的取指访问
#define vH_NES_Result_PRG_ReadFail                                -7   //意外的PRG读访问
#define vH_NES_Result_PRG_WriteFail                               -8   //意外的PRG写访问

#define vH_NES_Result_PPUError                                    -9   //PPU错误
#define vH_NES_Result_APUError                                    -10  //APU错误

#define vH_NES_Result_ParamError                                  -11




//用户需实现该接口中的方法
typedef struct{
  void* v;

  void (*ExitCallback)(void* v);//NES线程结束回调 该回调被调用时H_NES并没有完全退出, 需使用H_NES_Stop()来保证H_NES完全停止

  //线程相关方法
  struct{

    void* (*new_MessageQueue)(int QueueLength,int Size);//新建消息队列方法
    void (*delete_MessageQueue)(void* MessageQueue);//删除消息队列方法
    int (*MessageSned)(void* MessageQueue,void* p);//发送消息方法 返回0为成功
    void (*MessageReceive)(void* MessageQueue,void* p);//接收消息方法
    int (*MessageTryReceive)(void* MessageQueue,void* p);//尝试接收消息方法 返回0为成功

    void (*ThreadExit)(int RetVal);//退出线程回调 用于使线程退出
  }Thread;

  //主机相关接口
  struct{
    void (*RendersLine)(void* v,Hbyte* ColorIndexArray,unsigned int line);//传入一行的显示数据和所在行号(0~239) 传入的数据仅为颜色ID, 要经过调色板映射
    void (*AudioOutput)(void* v,void* Samples,int Length);//传入音频数据缓存和缓存音频样本数 缓存类型根据配置文件决定
    Huint16 (*GetStandardControllerStatus)(void* v);//标准控制器输入
  }Console;
}H_NES_LL_Function;




/**
 * @brief 新建一个主机
 * @param LL_Function 底层方法
 * @param Malloc 分配内存方法
 * @param Free 释放内存方法
 * @return 新建的主机句柄
 */
void* new_H_NES_Console(H_NES_LL_Function* LL_Function,void* (*Malloc)(Husize),void (*Free)(void*));

/**
 * @brief 释放主机句柄
 *        !!!注意 需要主机完全停止后才能调用(如果挂载了ROM,还需在完全停止后,调用本API之前调用卸载ROM的方法)
 * @param h_nes 主机句柄
 * @return 无
 */
void delete_H_NES_Console(void* h_nes);

/**
 * @brief 设置电视标准 必须在主机未运行时使用
 * @param h_nes 主机句柄
 * @param TelevisionStandards 电视标准vH_NES_TelevisionStandards_
 * @return 0:成功 其他:失败代号
 */
int H_NES_SetTelevisionStandards(void* h_nes,Hsize TelevisionStandards);

/**
 * @brief 根据映像头部16字节获取ROM信息
 * @param Header 头部16字节的头指针
 * @param PRG_ROM_Offset 用于返回PRG_ROM的偏移
 * @param PRG_ROM_Size 用于返回PRG_ROM的大小
 * @param CHR_ROM_Offset 用于返回CHR_ROM的偏移
 * @param CHR_ROM_Size 用于返回CHR_ROM的大小
 * @return 0:成功 其他:失败代号
 */
int H_NES_GetROM_Info(const void* Header
  ,Huint32* PRG_ROM_Offset,Huint32* PRG_ROM_Size
  ,Huint32* CHR_ROM_Offset,Huint32* CHR_ROM_Size);

/**
 * @brief 挂载ROM 须在主机未运行时使用
 * @param h_nes 主机句柄
 * @param NESROM ROM的指针, 指向.nes格式的内存区域
 * @return 0:成功 其他:失败代号
 */
int H_NES_LoadROM(void* h_nes,const void* NESROM);

/**
 * @brief 分散挂载ROM 须在主机未运行时使用
 * @param h_nes 主机句柄
 * @param Header 头部16字节的头指针
 * @param PRG_ROM PRG_ROM头部指针
 * @param CHR_ROM CHR_ROM头部指针
 * @return 0:成功 其他:失败代号
 */
int H_NES_LoadROM_Scatter(void* h_nes,const void* Header,const void* PRG_ROM,const void* CHR_ROM);

/**
 * @brief 卸载ROM 必须在主机未运行时使用
 * @param h_nes 主机句柄
 * @return 0:成功 其他:失败代号
 */
int H_NES_UnloadROM(void* h_nes);

/**
 * @brief 主机运行 将完全占用调用其的线程 并且如果出现意外或者用户调用使其停止的API 线程会终止
 * @param h_nes 主机句柄
 * @return 该方法不返回
 */
void H_NES_Start(void* h_nes);

/**
 * @brief 停止主机
 * @param h_nes 主机句柄
 * @return 无
 */
void H_NES_Stop(void* h_nes);

/**
 * @brief 启动会调用H_NES_Start()的线程后必须调用 该方法用于等待H_NES运行
 * @param h_nes 主机句柄
 * @return 0:成功 其他:失败代号
 */
int H_NES_WaitUntilRun(void* h_nes);

/**
 * @brief 获取主机是否在运行状态
 * @param h_nes 主机句柄
 * @return 0:未运行 其他:正在运行
 */
int H_NES_IsRun(void* h_nes);

/**
 * @brief 获取进度数据大小 加载ROM之后才能调用 进度大小与ROM有关, 加载ROM之后才能通过本API获取进度数据大小
 * @param h_nes 主机句柄
 * @return 进度大小
 */
int H_NES_GetProgressSize(void* h_nes);

/**
 * @brief 复位主机 主机运行时可调用
 * @param h_nes 主机句柄
 * @return 0:成功 其他:失败代号
 */
int H_NES_Reset(void* h_nes);

/**
 * @brief 获取进度 仅运行时可调用
 * @param h_nes 主机句柄
 * @param Progress 用于返回进度数据
 * @return 0:成功 其他:失败代号
 */
int H_NES_GetProgress(void* h_nes,void* Progress);

/**
 * @brief 加载进度 仅运行时可调用 H_NES并不会检查存档与ROM是否匹配, 如果尝试将存档加载到另一个游戏上, 可能会出现不可预料的后果(尤其是mapper不同的)
 * @param h_nes 主机句柄
 * @param Progress 进度数据
 * @return 0:成功 其他:失败代号
 */
int H_NES_LoadProgress(void* h_nes,void* Progress);

/**
 * @brief 设置Vblank触发NMI的延迟
 * @param h_nes 主机句柄
 * @param VblankNMI_Delay 延迟PPU时钟数
 * @return 0:成功 其他:失败代号
 */
int H_NES_SetVblankNMI_Delay(void* h_nes,Hint32 VblankNMI_Delay);

/**
 * @brief 设置MMC3触发计数器的延迟
 * @param h_nes 主机句柄
 * @param MMC3_CountDelay 延迟PPU时钟数
 * @return 0:成功 其他:失败代号
 */
int H_NES_SetMMC3_CountDelay(void* h_nes,Hint32 MMC3_CountDelay);

/**
 * @brief 获取返回值 在NES终止后可调用
 * @param h_nes 主机句柄
 * @return 返回值
 */
int H_NES_GetRetVal(void* h_nes);




#endif //__H_NES_H_
